package com.yx.robot.util;

import android.graphics.Point;
import android.graphics.PointF;

import java.util.ArrayList;
import java.util.List;

public class MapHandleUtils {
    public static PointF getRoomCenter(int roomTag, int[] src, int width, int height) {
        //rows = height cols = width
        int top = height;
        int left = width;
        int bottom = 0;
        int right = 0;

        boolean hasRoom=false;
        for (int i = 0; i < height; ++i) {
            for (int j = 0; j < width; ++j) {
                int id = src[i * width + j];
                if (id == roomTag) {
                    if (top > i) {
                        top = i;
                    }
                    if (left > j) {
                        left = j;
                    }
                    if (bottom < i) {
                        bottom = i;
                    }
                    if (right < j) {
                        right = j;
                    }
                    hasRoom=true;
                }
            }
        }
        if(!hasRoom){
            return null;
        }

        Point centerPoint = new Point((right + left) / 2, (bottom + top) / 2);
        int centerX = centerPoint.x;
        int centerY = centerPoint.y;

        Point leftP = new Point(left, centerY);
        Point rightP = new Point(right, centerY);
        List<Point> wCrossPoints = ktest_getRoomCrossFrom(leftP, rightP, roomTag, src,width,height);
        if (wCrossPoints.size() >= 2) {
            Point p1 = wCrossPoints.get(0);
            Point p2 = wCrossPoints.get(wCrossPoints.size() - 1);
            centerX = (p2.x + p1.x) / 2;
        }
        Point topP = new Point(centerX, top);
        Point bottomP = new Point(centerX, bottom);
        List<Point> hCrossPoints = ktest_getRoomCrossFrom(topP, bottomP, roomTag, src,width,height);
        if (hCrossPoints.size() >= 2) {
            //如果竖向的切点超过两个 先取前后两点的中心 确认是否在房间内
            Point p1 = hCrossPoints.get(0);
            Point p2 = hCrossPoints.get(hCrossPoints.size() - 1);
            centerY = (p2.y + p1.y) / 2;
            int kRoomID = src[centerY * width + centerX];
            if (kRoomID != roomTag) {
                //如果最前最后两点的中心点非房间点--找两两切点之间距离最长的最为中心
                int maxI = 0;
                double maxDistance = 0;
                for (int i = 0; i < hCrossPoints.size() / 2; i++) {
                    if (i * 2 + 1 > hCrossPoints.size() - 1) {
                        break;
                    }
                    Point p3 = hCrossPoints.get(i * 2);
                    Point p4 = hCrossPoints.get(i * 2 + 1);
                    double distance = Math.floor(Math.sqrt(Math.pow((p3.x - p4.x), 2) + Math.pow((p3.y - p4.y), 2)));
                    if (distance > maxDistance) {
                        maxDistance = distance;
                        maxI = i;
                    }
                }
                Point kp1 = hCrossPoints.get(maxI * 2);
                Point kp2 = hCrossPoints.get(maxI * 2 + 1);
                centerY = (kp2.y + kp1.y) / 2;
            }
        }

        PointF resultP = new PointF();
        resultP.x = centerX;
        resultP.y = centerY;
        return resultP;
    }

    public static List<Point> ktest_getRoomCrossFrom(Point start, Point end, int roomID, int[] src,  int w, int h) {
        List<Point> linePoints = getLineInterpolation(start, end);
        List<Point> result = new ArrayList<>();
        for (int i = 0; i < linePoints.size(); i++) {
            Point point = linePoints.get(i);
            int x = point.x;
            int y = point.y;
            int kRoomID = src[y * w + x];
            if (kRoomID == roomID) {
                //如果当前点 前一个点 后一个点 都是当前房间ID--不计入切点
                if (i > 0 && i < linePoints.size() - 1) {
                    //前一个点 后一个点都存在
                    Point lastPoint = linePoints.get(i - 1);
                    int lastX = lastPoint.x;
                    int lastY = lastPoint.y;
                    int kLastRoomID = src[lastY * w + lastX];

                    Point nextPoint = linePoints.get(i + 1);
                    int nextX = nextPoint.x;
                    int nextY = nextPoint.y;
                    int kNextRoomID = src[nextY * w + nextX];
                    if (kLastRoomID == kRoomID && kNextRoomID == kRoomID) {
                        continue;
                    }
                }
                boolean add = true;
                for (int j = 0; j < result.size(); j++) {
                    Point kp = result.get(j);
                    if (kp.x == point.x && kp.y == point.y) {
                        add = false;
                        break;
                    }
                }
                if (!add) {
                    continue;
                }
                result.add(point);
            }

        }
        List<Point> fixResult = ktext_fixCrossPoints(result);
        return fixResult;
    }

    public static List<Point> ktext_fixCrossPoints(List<Point> points) {
        if (points.size() < 4) {
            return points;
        }

        List<Point> results = new ArrayList<>();
        List<Point> temPoints = new ArrayList<>();
        temPoints.addAll(points);
        while (temPoints.size() >= 4) {
            Point p1 = temPoints.get(1);
            Point p2 = temPoints.get(2);
            double distance = Math.floor(Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2)));
            if (distance < 10) {
                temPoints.remove(1);
                temPoints.remove(1);
            } else {
                results.add(temPoints.get(0));
                results.add(temPoints.get(1));
                temPoints.remove(0);
                temPoints.remove(0);
            }
        }
        results.addAll(temPoints);
        return results;
    }

    //两点之间插值
    public static List<Point> getLineInterpolation(Point start, Point end) {
        List<Point> result = new ArrayList<>();
        result.add(start);
        double distance = Math.floor(Math.sqrt(Math.pow((start.x - end.x), 2) + Math.pow((start.y - end.y), 2)));
        if (distance > 1) {
            double step = 1 / distance;
            double startRatio = 0.0;
            Point prePosition = start;
            for (int j = 0; j < distance; j++) {
                startRatio += step;
                Point r = new Point();
                r.x = (int) (start.x + (end.x - start.x) * startRatio);
                r.y = (int) (start.y + (end.y - start.y) * startRatio);
                if (!r.equals(prePosition)) {
                    result.add(r);
                    prePosition = r;
                }
            }
        }
        result.add(end);
        return result;
    }
}
